package com.example.cscot.ui.cot;

import android.graphics.Color;
import android.os.Bundle;
import android.text.Layout;
import android.text.method.ScrollingMovementMethod;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.AdapterView;
import android.widget.ArrayAdapter;
import android.widget.Button;
import android.widget.EditText;
import android.widget.ImageView;
import android.widget.Spinner;
import android.widget.TextView;

import androidx.annotation.NonNull;
import androidx.fragment.app.Fragment;

import com.example.cscot.LewayHelper;
import com.example.cscot.LewayTimer;
import com.example.cscot.LewayWindow;
import com.example.cscot.R;
import com.example.cscot.RtCallback;
import com.example.cscot.WeiLe;
import com.example.cscot.databinding.FragmentCotBinding;

import org.json.JSONArray;

import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.List;

public class CotFragment extends Fragment {
    private FragmentCotBinding binding;
    public TextView mTvSteps;
    public TextView mTvBody;
    public EditText mEtBody; // et/vt是叠放的，每次只有一个是visible/gone，确保不冲突
    public TextView mTvQuestions;
    public LewayWindow mLw;
    Button mBtn1;
    Button mBtn2;
    Button mBtn3;
    Button mBtn4;
    Button mBtn5;
    String[] mQ;
    char [] mA;

    public static String TS() {
        return LocalDateTime.now().format(DateTimeFormatter.ofPattern("dd日HH:mm:ss.SSS "));
    }
    //
    // 未解之谜，如果连续两次加载长题目，就会出现layout变化，scroll失效，重新加载空文件可恢复
    // 以后再解这个问题
    public void bodyAppend(String body) {
        mTvBody.setText("");
        WeiLe.gCotBody = "";
        restoreTextViews();
        //
        // 先找题目，算法和题目的文件格式相关
        String[] lines = body.split("\\n");
        int i = 0;
        for (i = 0; i < lines.length - 3; i++) {
            mTvBody.append(lines[i] + "\n");
            if ((lines[i+2].length() > 2) && (lines[i+2].startsWith("[A")) &&
                    (lines[i+3].length() > 2) && (lines[i+3].startsWith("[B"))) {
                break;
            }
        }
        // 再找问题，每个选项必须是每行以A. B. C. D.开头，每个选项只占一行
        int iq = 1;
        for (; i < lines.length - 3; i++) {
            if ((lines[i+1].length() > 2) && (lines[i+1].startsWith("[A")) &&
                    (lines[i+2].length() > 2) && (lines[i+2].startsWith("[B"))) {
                mQ[iq] = lines[i] + "\n" + lines[i+1] + "\n" + lines[i+2] + "\n" +
                        lines[i+3] + "\n" + lines[i+4] + "\n";
                iq += 1;
            }
        }
        // 再找答案：答案 B A A B C
        int ia = 1;
        for (; i < lines.length; i++) {
            if (lines[i].contains("答案")) {
                // 一个中文只算一个？反正只能+2，不能+4
                for (int j = lines[i].indexOf("答案") + 2; j < lines[i].length(); j++) {
                    if (('A' <= lines[i].toCharArray()[j]) && (lines[i].toCharArray()[j] <= 'D')) {
                        mA[ia] = lines[i].toCharArray()[j];
                        WeiLe.gLogText += TS() + ia + " answer=" + mA[ia] + "\n";
                        ia++;
                    }
                }
                break;
            }
        }
        // 处理完毕
    } // >>> bodyAppend

    public View onCreateView(@NonNull LayoutInflater inflater,
                             ViewGroup container, Bundle savedInstanceState) {
        binding = FragmentCotBinding.inflate(inflater, container, false);
        View root = binding.getRoot();
        //
        mLw = new LewayWindow();
        //
        mTvSteps = root.findViewById(R.id.tvSteps);
        mTvSteps.setMovementMethod(ScrollingMovementMethod.getInstance());
        mTvSteps.setText(WeiLe.gEnglishSteps);
        mTvSteps.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                // 获取TextView的布局
                Layout layout = mTvSteps.getLayout();
                // 获取当前TextView中的光标位置
                int currentCursorPosition = mTvSteps.getSelectionStart();
                // 获取当前点击位置所在的行号
                int currentLine = layout.getLineForOffset(currentCursorPosition);
                // 获取行的开始偏移量和结束偏移量
                int lineStart = layout.getLineStart(currentLine);
                int lineEnd = layout.getLineEnd(currentLine);
                // 获取当前行的内容
                String currentLineText = mTvSteps.getText().subSequence(lineStart, lineEnd).toString();
                // mainActivity.showToast(currentLineText + " hello " + mTvSteps.getLineCount());
                loadMindMap(currentLineText);
            }
        });
        //
        mQ = new String[6];             // 第0个不用
        mA = "ZZZZZZ".toCharArray();    // 答案为必错的
        mTvBody = root.findViewById(R.id.tvBody);
        mTvBody.setMovementMethod(ScrollingMovementMethod.getInstance());
        mEtBody = root.findViewById(R.id.etBody);
        mEtBody.setMovementMethod(ScrollingMovementMethod.getInstance());
        mTvQuestions = root.findViewById(R.id.tvQuestions);
        mTvQuestions.setMovementMethod(ScrollingMovementMethod.getInstance());

        Button btn;
        btn = root.findViewById(R.id.btnPicture);
        btn.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                WeiLe.mainActivity.showToast("Not implemented yet, please be patient to wait.");
            }
        });
        btn = root.findViewById(R.id.btnFeynman);
        mBtn1 = btn;
        btn.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                if (WeiLe.gToTeach) {
                    WeiLe.mainActivity.showToast("请先完成当前的费曼复述，教学相长任务。");
                    return;
                } else {
                    WeiLe.gToTeach = true;
                    mTvBody.setVisibility(View.GONE);
                    mEtBody.setVisibility(View.VISIBLE);
                }
                if (WeiLe.gHashMap.containsKey("_STR_FMN")) {
                    mEtBody.setMaxWidth(mEtBody.getWidth());    // ET需要设置这个才不会变长
                    mEtBody.setText("");
                    // mEtBody.append(myApplication.gHashMap.get("_STR_FMN"));
                    mEtBody.append("我认为学习英语阅读理解应该这样做，");
                    WeiLe.mainActivity.showToast("请在红框内完成你的讲解，在你文本讲解完毕后，智启会反馈你的讲解");
                } else {
                    WeiLe.mainActivity.showToast("no _STR_FMN found " + WeiLe.gHashMap.size());
                    return;
                }
            }
        });
        btn = root.findViewById(R.id.btnVoice);
        // 修正这里的 mBtn1 重复赋值问题，应该使用一个新的按钮变量
        mBtn2 = btn; // 假设这是第二个按钮
        btn.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                WeiLe.mainActivity.showToast("Not implemented yet, 请先进行文字讲解，" +
                        "记住教学相长，你会掌握学霸思维的，加油！");
            }
        });
        btn = root.findViewById(R.id.btnTeach);
        btn.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                String myExp = mEtBody.getText().toString();
                if (!WeiLe.gToTeach) {
                    WeiLe.mainActivity.showToast("请先点击-费曼教-进入费曼教学相长模式，先准备好你的讲解材料。");
                    return;
                }
                // 1、准备提示，等待AI的评价
                mEtBody.append("\n\n智启：谢谢您用心的讲解，以下是我的一些反馈供您参考。\n");
                // 2、准备让AI来评价你的讲解，分析结果应该呈现在tvQuestions中
                String userChat = "";
                userChat += LewayHelper.readRawFile(WeiLe.mainActivity, "prp_exp") + "\n";
                userChat += "下面是一个同学对于如何做英语阅读理解的心得体会：";
                userChat += myExp;
                userChat += "。以上就是他的心得体会。\n";
                userChat += "请一步步地思考。第一步，对他的心得做一个总结，字数控制在100字左右。";
                userChat += "第二步，对他的心得和您的解题方法的相似度做评估打分，按A/B/C/D档打分，";
                userChat += "也就是从完全吻合，基本吻合，不吻合到有冲突。";
                userChat += "第三步，简单描叙您的解题方法，字数控制在120字左右";
                userChat += "第四步，对他的进一步学习英语阅读理解提出一些建议和鼓励。\n";
                WeiLe.gLogText += TS() + userChat;  // 调试信息
                // 3、发送请求到AI
                JSONArray array = new JSONArray();
                WeiLe.gCotLlm.postChats(array, userChat, new RtCallback() {
                    @Override
                    public void onRightTime(String strResult) {
                        WeiLe.gLogText += LewayHelper.logLine(strResult);
                        doCbFeynman(strResult);
                    }
                });
                // 4、确保5秒钟后执行，其实这是有问题，但是现在LewayChat不支持mSessionDone
                // 只能假定第一次回来后的5秒内，肯定会全部回来。
                LewayTimer lt = new LewayTimer(5000, new RtCallback() {
                    @Override
                    public void onRightTime(String strResult) {
                        // 所有UI元素都必须在UIThread中执行
                        WeiLe.mainActivity.runOnUiThread(() -> {
                            mTvBody.append("\n\n要想做好阅读理解，我们必须掌握好正确的学霸思维方式，");
                            mTvBody.append("通过链式思维方式，逐步掌握全局性的，系统性的阅读理解知识图谱。");
                            LewayHelper.scrollToEnd(mTvBody);
                            if (!mTvBody.getText().toString().isEmpty()) {
                                WeiLe.gCotBody = mTvBody.getText().toString(); // 保存起来
                            }
                        });
                    }
                }, true);
            }
        });
        btn = root.findViewById(R.id.btnQ1);
        mBtn1 = btn;
        btn.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                doQclick(mBtn1, 1);
            }
        });
        btn = root.findViewById(R.id.btnQ2);
        mBtn2 = btn;
        btn.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                doQclick(mBtn2, 2);
            }
        });
        btn = root.findViewById(R.id.btnQ3);
        mBtn3 = btn;
        btn.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                doQclick(mBtn3, 3);
            }
        });
        btn = root.findViewById(R.id.btnQ4);
        mBtn4 = btn;
        btn.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                doQclick(mBtn4, 4);
            }
        });
        btn = root.findViewById(R.id.btnQ5);
        mBtn5 = btn;
        btn.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                doQclick(mBtn5, 5);
            }
        });
        btn = root.findViewById(R.id.btnSubmit);
        btn.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                if (WeiLe.gToTeach) {
                    WeiLe.mainActivity.showToast("请先完成当前的费曼复述，教学相长任务。");
                    return;
                }
                mEtBody.setVisibility(View.GONE);
                mTvBody.setVisibility(View.VISIBLE);
                int cntWrong = 0;
                // not done
                if (WeiLe.gAnswer[1] != mA[1]) {
                    cntWrong += 1;
                    mBtn1.setBackgroundColor(0xffee3f4d);
                }
                else{
                    mBtn1.setBackgroundColor(0xff229453);
                }
                if (WeiLe.gAnswer[2] != mA[2]) {
                    cntWrong += 1;
                    mBtn2.setBackgroundColor(0xffee3f4d);
                }
                else{
                    mBtn2.setBackgroundColor(0xff229453);
                }
                if (WeiLe.gAnswer[3] != mA[3]) {
                    cntWrong += 1;
                    mBtn3.setBackgroundColor(0xffee3f4d);
                }
                else{
                    mBtn3.setBackgroundColor(0xff229453);
                }
                if (WeiLe.gAnswer[4] != mA[4]) {
                    cntWrong += 1;
                    mBtn4.setBackgroundColor(0xffee3f4d);
                }
                else{
                    mBtn4.setBackgroundColor(0xff229453);
                }
                if (WeiLe.gAnswer[5] != mA[5]) {
                    cntWrong += 1;
                    mBtn5.setBackgroundColor(0xffee3f4d);
                }
                else{
                    mBtn5.setBackgroundColor(0xff229453);
                }
                // 1、特殊的初始化，题目提交后，显示答案
                WeiLe.mainActivity.showToast("一共5道题，你错啦" + cntWrong + "题，加油！");
                // 2、准备让AI来做题，并展示思维步骤
                String userChat = "";
                userChat += LewayHelper.readRawFile(WeiLe.mainActivity, "prp_exp") + "\n";
                userChat += "下面是一篇英语阅读理解题：\n";
                userChat += mTvBody.getText().toString() + "\n";
                userChat += mQ[1] + "\n";
                userChat += mQ[2] + "\n";
                userChat += mQ[3] + "\n";
                userChat += mQ[4] + "\n";
                userChat += mQ[5] + "\n";
                userChat += "请一步步地思考，利用你的解题方法讲解这道阅读理解题。" + "\n";
                WeiLe.gLogText += TS() + userChat;
                // 3、先换行
                mTvBody.append("\n");
                // 4、发Request到服务器
                JSONArray array = new JSONArray();
                WeiLe.gCotLlm.postChats(array, userChat, new RtCallback() {
                    @Override
                    public void onRightTime(String strResult) {
                        WeiLe.gLogText += LewayHelper.logLine(strResult); // 调试信息
                        doCb(strResult);
                    }
                });
                // 5、确保5秒钟后执行，其实这是有问题的，但是现在LewayChat不支持mSessionDone
                // 只能假定5秒内，肯定会全部回来。
                LewayTimer lt = new LewayTimer(5000, new RtCallback() {
                    @Override
                    public void onRightTime(String strResult) {
                        // 所有UI元素都必须在UIThread中执行
                        WeiLe.mainActivity.runOnUiThread(() -> {
                            mTvBody.append("\n\n要想做好阅读理解，我们必须掌握好正确的学霸思维方式，");
                            mTvBody.append("通过链式思维方式，逐步掌握全局性的，系统性的阅读理解知识图谱。");
                            LewayHelper.scrollToEnd(mTvBody);
                            if (!mTvBody.getText().toString().isEmpty()) {
                                WeiLe.gCotBody = mTvBody.getText().toString(); // 保存起来
                            }
                        });
                    }
                }, true);
            }
        });

        // others
        List<String> listFiles = LewayHelper.getRawFiles(WeiLe.mainActivity);
        WeiLe.gRawFiles.clear();
        WeiLe.gRawFiles.add("请选择"); // 添加默认选项
        WeiLe.gRawFiles.add("自定义题目");
        for (int i = 0; i < listFiles.size(); i++) {
            if (listFiles.get(i).contains("english")) {
                WeiLe.gRawFiles.add(listFiles.get(i));
            }
            WeiLe.gLogText += TS() + listFiles.get(i) + "\n";
        }

        // 获取cbSpinner组件
        Spinner cbSpinner = root.findViewById(R.id.cbSpinner);
        // 创建一个ArrayAdapter实例，并添加默认选项“请选择”
        ArrayAdapter<CharSequence> cbAdapter =
                new ArrayAdapter<>(WeiLe.mainActivity, android.R.layout.simple_list_item_1,
                        WeiLe.gRawFiles.toArray(new String[WeiLe.gRawFiles.size()]));
        cbSpinner.setAdapter(cbAdapter);

        // 添加监听器
        cbSpinner.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {
            @Override
            public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {
                WeiLe.gToTeach = false; // 中止费曼模式
                mEtBody.setVisibility(View.GONE);
                mTvBody.setVisibility(View.VISIBLE);
                String selected = parent.getItemAtPosition(position).toString();
                WeiLe.gLogText += TS() + selected + "\n";
                if (!selected.equals("请选择")) { // 排除默认选项
                    bodyAppend(LewayHelper.readRawFile(WeiLe.mainActivity, selected));

                    // 处理完选择后，重置 Spinner 选择回默认选项
                    parent.setSelection(0);
                }
                LewayHelper.scrollToEnd(mTvBody);
                // mTvBody.setText(myApplication.readRawFile(mainActivity, selected));
            }

            @Override
            public void onNothingSelected(AdapterView<?> parent) {
                // 当没有选项被选中时的回调
            }
        });

        // 设置 abcdSpinner 的适配器，并添加默认选项“请选择”
        Spinner abcdSpinner = root.findViewById(R.id.abcdSpinner);
        ArrayAdapter<CharSequence> abcdAdapter =
                new ArrayAdapter<>(WeiLe.mainActivity, android.R.layout.simple_spinner_item,
                        new String[]{"请选择", "A", "B", "C", "D"});
        abcdAdapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
        abcdSpinner.setAdapter(abcdAdapter);

        abcdSpinner.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {
            @Override
            public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {
                WeiLe.gToTeach = false; // 中止费曼模式
                String selected = parent.getItemAtPosition(position).toString();
                WeiLe.gLogText += TS() + selected + "\n";
                if (!selected.equals("请选择")) { // 排除默认选项
                    if ((1 <= WeiLe.gQid) && (WeiLe.gQid <= 5)) {
                        if (selected.equals("单选")) {
                            WeiLe.gAnswer[WeiLe.gQid] = '?';
                            WeiLe.gBtn.setText(String.valueOf('?'));
                        } else {
                            WeiLe.gAnswer[WeiLe.gQid] = selected.charAt(0);
                            WeiLe.gBtn.setText(selected);
                        }
                    } else {
                        WeiLe.gLogText += TS() + "illegal qId " + WeiLe.gQid + "\n";
                    }

                    // 处理完选择后，重置 Spinner 选择回默认选项
                    parent.setSelection(0);
                }
            }

            @Override
            public void onNothingSelected(AdapterView<?> parent) {
                // 当没有选项被选中时的回调
            }
        });
        //
        restoreTextViews();
        //
        return root;
    } // onCreate

    @Override
    public void onResume() {
        super.onResume();
        //
        restoreTextViews();
        //
        WeiLe.gLogText += TS() + mTvBody.getHeight() + " height Resume\n";
        WeiLe.gLogText += TS() + mTvBody.getMaxHeight() + " maxHeight Resume\n";
        WeiLe.gLogText += TS() + mTvBody.getLineHeight() + " lineHeight Resume\n";
        WeiLe.gLogText += TS() + WeiLe.gCotBwidth + " maxWidth Resume\n";
        WeiLe.gLogText += TS() + WeiLe.gCotBheight + " maxHeight Resume\n";
    } // >>> onResume

    @Override
    public void onDestroyView() {
        super.onDestroyView();
        binding = null;
    } // >>>onDestroy
    //
    public void restoreTextViews() {
        if (WeiLe.gCotBheight <= 0) {
            WeiLe.gCotBheight = mTvBody.getHeight();
        }
        if (WeiLe.gCotBwidth <= 0) {
            WeiLe.gCotBwidth = mTvBody.getWidth();
        }
        //
        if (WeiLe.gCotQheight <= 0) {
            WeiLe.gCotQheight = mTvQuestions.getHeight();
        }
        if (WeiLe.gCotQwidth <= 0) {
            WeiLe.gCotQwidth = mTvQuestions.getWidth();
        }
        //
        mTvBody.setWidth(WeiLe.gCotBwidth);
        mTvBody.setHeight(WeiLe.gCotBheight);
        mTvBody.setMaxWidth(WeiLe.gCotBwidth);
        mTvBody.setMaxHeight(WeiLe.gCotBheight);
        //
        mTvQuestions.setWidth(WeiLe.gCotQwidth);
        mTvQuestions.setHeight(WeiLe.gCotQheight);
        mTvQuestions.setMaxWidth(WeiLe.gCotQwidth);
        mTvQuestions.setMaxHeight(WeiLe.gCotQheight);
        //
        if (!WeiLe.gCotBody.isEmpty()) {
            mTvBody.setText(WeiLe.gCotBody);
        }
        if (!WeiLe.gCotQuestions.isEmpty()) {
            mTvQuestions.setText(WeiLe.gCotQuestions);
        }
        int y;
        //
        if (mTvBody.getLayout() != null) {
            y = mTvBody.getLayout().getLineTop(mTvBody.getLineCount()) - mTvBody.getHeight();
            mTvBody.scrollTo(0, y);
        }
        if (mTvQuestions.getLayout() != null) {
            // y = mTvQuestions.getLayout().getLineTop(mTvQuestions.getLineCount()) - mTvQuestions.getHeight();
            // mTvQuestions.scrollTo(0, y);
        }
        //
        return;
    }
    //
    public void doQclick(Button btn, int i) {
        if (WeiLe.gBtn != null) {
            WeiLe.gBtn.setBackgroundColor(0xff2177b8);   // 复原颜色
        }
        WeiLe.gQid = i;
        WeiLe.gBtn = btn;
        btn.setBackgroundColor(Color.GRAY);
        btn.setText(String.valueOf(WeiLe.gAnswer[i]));
        restoreTextViews();
        mTvQuestions.setText("");
        if (mQ[i] != null) {
            mTvQuestions.setText(mQ[i]);
        }
        if (!mTvQuestions.getText().toString().isEmpty()) {
            WeiLe.gCotQuestions = mTvQuestions.getText().toString();
        }
    }

    public void loadMindMap(String step) {
        step = step.strip();
        if (step.isEmpty()) {
            return;
        }
        if (step.contains("全貌")) {
            step = "overview_big";
        }
        if (step.contains("基本功词句段")) {
            step = "basic_capability";
        }
        if (step.contains("生词不生")) {
            step = "unknown_word";
        }
        if (step.contains("括号法")) {
            step = "kuohaofa";
        }
        if (step.contains("句子5功能")) {
            step = "sentence_function";
        }
        if (step.contains("句子10结构")) {
            step = "sentense_structure";
        }
        if (step.contains("答题步骤5原则")) {
            step = "resolution_steps";
        }
        if (step.contains("7种宏观题a")) {
            step = "macro7_13";
        }
        if (step.contains("7种宏观题b")) {
            step = "macro7_45";
        }
        if (step.contains("7种宏观题c")) {
            step = "macro7_567";
        }
        if (step.contains("7大微观题a")) {
            step = "micro7_12";
        }
        if (step.contains("7大微观题b")) {
            step = "micro7_47";
        }
        if (step.contains("选项3+12特点")) {
            step = "good_wrong_option";
        }
        if (step.contains("正确选项3特点")) {
            step = "option_pattern";
        }
        if (step.contains("错误选项12类")) {
            step = "option_pattern_4_10";
        }
        if (step.contains("选项题干规律")) {
            step = "two_pattern";
        }
        if (step.contains("题干文章规律")) {
            step = "patter23";
        }
        if (step.contains("文章总体规律")) {
            step = "overall_pattern";
        }
        if (step.contains("记叙文规律")) {
            step = "text_pattern";
        }
        if (step.contains("议论文规律")) {
            step = "text_pattern24";
        }

        int fileId = WeiLe.mainActivity.getResources().getIdentifier(step, "drawable",
                WeiLe.mainActivity.getPackageName());
        if (fileId > 0) {
            ImageView iv = mLw.addImageView(0, 40, mLw.mScreenWidth, mLw.mScreenHeight - 80, 0, fileId);
            iv.setScaleType(ImageView.ScaleType.FIT_XY);
            // Matrix matrix = iv.getImageMatrix();
            // matrix.postRotate(90.0f);
            // iv.setImageMatrix(matrix);
        } else {
            // mainActivity.showToast("No image found for [" + step + "]" );
        }
        return;
    } // >>> loadMindMap
    //
    public void doCb(String cbResult) {
        WeiLe.mainActivity.runOnUiThread(() -> {
            // restoreTextViews();
            // mTvBody.append(cbResult);
            mTvBody.setMaxWidth(mTvBody.getWidth());
            mTvBody.append(cbResult);
            LewayHelper.scrollToEnd(mTvBody);
        });
    } // doCb
    //
    public void doCbFeynman(String cbResult) {
        // 要更新UI元素，就必须runOnUiThread()
        WeiLe.mainActivity.runOnUiThread(() -> {
            mEtBody.setMaxWidth(mEtBody.getWidth());
            mEtBody.append(cbResult);
            LewayHelper.scrollToEnd(mEtBody);
        });
    } // doCbFeynman
} // >>> fragment
